package com.netflexitysolutions.amazonws.ec2;

import java.util.List;
import java.util.Set;

import com.amazonaws.ec2.doc._2009_04_04.AmazonEC2PortType;

/**
 * @author lordorient
 *
 */
/**
 * @author lordorient
 *
 */
public interface EC2 {
	
	//////////////////////////////
	//  Operations with images  //
	//////////////////////////////
	
	/**
	 * @param pathToImage
	 * @return
	 * @throws EC2Exception
	 */
	public abstract String registerImage(String pathToImage) throws EC2Exception;
	
	/**
	 * @param imageIds
	 * @param ownedBy
	 * @param executableBy
	 * @return
	 * @throws EC2Exception
	 */
	public abstract List<ImageDescription> describeImages(Set<String> imageIds, 
			Set<String> ownedBy, Set<String> executableBy) throws EC2Exception;
	
	/**
	 * @param imageId
	 * @return
	 * @throws EC2Exception
	 */
	public abstract boolean deregisterImage(String imageId) throws EC2Exception;
	
	//////////////////////////////////
	//  Image attributes operations //
	//////////////////////////////////

	/**
	 * @param imageId
	 * @return
	 * @throws EC2Exception
	 */
	public abstract List<LaunchPermission> getLaunchPermitions(String imageId) throws EC2Exception;
	
	/**
	 * @param imageId
	 * @return
	 * @throws EC2Exception
	 */
	public abstract List<BlockDeviceMapping> getBlockDeviceMappings(String imageId) throws EC2Exception;
	
	/**
	 * @param imageId
	 * @param attribute
	 * @return
	 * @throws EC2Exception
	 */
	public abstract String getSimpleAttribute(String imageId, ImageSimpleAttributeType attribute) throws EC2Exception;
	
	/**
	 * @param imageId
	 * @return
	 * @throws EC2Exception
	 */
	public abstract List<String> getProductCodes(String imageId) throws EC2Exception;
	
	/**
	 * @param imageId
	 * @param permission
	 * @return
	 * @throws EC2Exception
	 */
	public abstract boolean addLaunchPermission(String imageId, LaunchPermission permission) throws EC2Exception;
	
	/**
	 * @param imageId
	 * @param permissions
	 * @return
	 * @throws EC2Exception
	 */
	public abstract boolean addLaunchPermissions(String imageId, List<LaunchPermission> permissions) throws EC2Exception;
	
	/**
	 * @param imageId
	 * @param permission
	 * @return
	 * @throws EC2Exception
	 */
	public abstract boolean removeLaunchPermission(String imageId, LaunchPermission permission) throws EC2Exception;
	
	/**
	 * @param imageId
	 * @param permissions
	 * @return
	 * @throws EC2Exception
	 */
	public abstract boolean removeLaunchPermissions(String imageId, List<LaunchPermission> permissions) throws EC2Exception;
	
	/**
	 * @param imageId
	 * @param productCode
	 * @return
	 * @throws EC2Exception
	 */
	public abstract boolean setProductCode(String imageId, String productCode) throws EC2Exception;
	
	/**
	 * @param imageId
	 * @param attribute ImageAttributeType, for now only LAUNCH_PERMISSION is supported
	 * @return true, if attribute was successfuly reset; false, if underlying service returned false, 
	 * 				or reset of this attribute is not supported 
	 * @throws EC2Exception
	 */
	public abstract boolean resetImageAttribute(String imageId, ImageAttributeType attribute) throws EC2Exception;
	
	/////////////////////////
	// Instance operations //
	/////////////////////////
	
	/**
	 * @param instanceId
	 * @return
	 * @throws EC2Exception
	 */
	public abstract RunningInstance describeInstance(String instanceId) throws EC2Exception;

	/**
	 * @param instanceIds
	 * @return
	 */
	public abstract List<RunningInstance> describeInstances(Set<String> instanceIds) throws EC2Exception;

	/**
	 * @param instanceIds
	 * @return
	 */
	public abstract boolean rebootInstances(Set<String> instanceIds) throws EC2Exception;

	/**
	 * @param params
	 * @return
	 */
	public abstract List<RunningInstance> runInstances(InstanceStartupParameters params) throws EC2Exception;

	/**
	 * @param instanceId
	 * @return
	 * @throws EC2Exception
	 */
	public abstract InstanceTerminationResult terminateInstance(String instanceId) throws EC2Exception;
	
	/**
	 * @param instanceIds
	 * @return
	 * @throws EC2Exception
	 */
	public abstract List<InstanceTerminationResult> terminateInstances(Set<String> instanceIds) throws EC2Exception;
	
	/**
	 * @param instanceIds
	 * @return
	 */
	public abstract List<ReservedInstances> describeReservedInstances(Set<String> instanceIds) throws EC2Exception;

	/**
	 * @param examples a list of offerings that serve as example for offering search. 
	 * @return
	 * @throws EC2Exception
	 */
	public abstract List<ReservedInstancesOffering> describeReservedInstancesOfferings(Set<String> instancesOfferingIds,
			InstanceType instanceType, String availabilityZone, String productDescription) throws EC2Exception;

	/**
	 * @param reservedInstancesOfferingId
	 * @return
	 * @throws EC2Exception
	 */
	public abstract String purchaseReservedInstancesOffering(String reservedInstancesOfferingId) throws EC2Exception; 
	
	/**
	 * @param reservedInstancesOfferingId
	 * @param instanceCount
	 * @return
	 * @throws EC2Exception
	 */
	public abstract String purchaseReservedInstancesOffering(String reservedInstancesOfferingId, int instanceCount) throws EC2Exception; 
	
	////////////////////////////////
	// Security groups operations //
	////////////////////////////////
	
	/**
	 * @param userId
	 * @param groupName
	 * @param secGroupName
	 * @param secGroupOwnerId
	 * @return
	 * @throws EC2Exception
	 */
	public abstract boolean authorizeSecurityGroupIngress(String userId, String groupName, String secGroupName,
			String secGroupOwnerId) throws EC2Exception;

	/**
	 * @param userId
	 * @param groupName
	 * @param ipProtocol
	 * @param fromPort
	 * @param toPort
	 * @param cidrIp
	 * @return
	 * @throws EC2Exception
	 */
	public abstract boolean authorizeSecurityGroupIngress(String userId, String groupName, IPProtocol ipProtocol,
									int fromPort, int toPort, String cidrIp) throws EC2Exception;

	/**
	 * @param name
	 * @param description
	 * @return
	 * @throws EC2Exception
	 */
	public abstract boolean createSecurityGroup(String name, String description) throws EC2Exception;

	/**
	 * @param userId
	 * @param groupName
	 * @param ipProtocol
	 * @param fromPort
	 * @param toPort
	 * @param cidrIp
	 * @return
	 * @throws EC2Exception
	 */
	public abstract boolean revokeSecurityGroupIngress(String userId, String groupName, IPProtocol ipProtocol,
									int fromPort, int toPort, String cidrIp) throws EC2Exception;

	/**
	 * @param userId
	 * @param groupName
	 * @param secGroupName
	 * @param secGroupOwnerId
	 * @return
	 * @throws EC2Exception
	 */
	public abstract boolean revokeSecurityGroupIngress(String userId, String groupName, String secGroupName,
			String secGroupOwnerId) throws EC2Exception;

	/**
	 * @param name
	 * @return
	 * @throws EC2Exception
	 */
	public abstract boolean deleteSecurityGroup(String name) throws EC2Exception;

	/**
	 * @return
	 * @throws EC2Exception
	 */
	public abstract List<SecurityGroup> describeSecurityGroups() throws EC2Exception;

	/**
	 * @param groupNames
	 * @return
	 * @throws EC2Exception
	 */
	public abstract List<SecurityGroup> describeSecurityGroups(Set<String> groupNames) throws EC2Exception;

	//////////////////////////
	// Key pairs operations //
	//////////////////////////
	
	/**
	 * @param keyName
	 * @return
	 * @throws EC2Exception
	 */
	public abstract KeyPair createKeyPair(String keyName) throws EC2Exception;

	/**
	 * @param keyName
	 * @return
	 * @throws EC2Exception
	 */
	public abstract boolean deleteKeyPair(String keyName) throws EC2Exception;

	/**
	 * @return
	 * @throws EC2Exception
	 */
	public abstract List<KeyPair> describeKeyPairs() throws EC2Exception;
	
	/**
	 * @param keyNames
	 * @return
	 * @throws EC2Exception
	 */
	public abstract List<KeyPair> describeKeyPairs(Set<String> keyNames) throws EC2Exception;
	
	//////////////////////////////////
	// zones and regions operations //
	//////////////////////////////////

	/**
	 * @return
	 * @throws EC2Exception
	 */
	public abstract List<AvailabilityZone> describeAvailabilityZones() throws EC2Exception; 

	/**
	 * @param zoneNames
	 * @return
	 * @throws EC2Exception
	 */
	public abstract List<AvailabilityZone> describeAvailabilityZones(Set<String> zoneNames) throws EC2Exception; 

	/**
	 * @return
	 * @throws EC2Exception
	 */
	public abstract List<Region> describeRegions() throws EC2Exception;  
	
	/**
	 * @param regionNames
	 * @return
	 * @throws EC2Exception
	 */
	public abstract List<Region> describeRegions(Set<String> regionNames) throws EC2Exception;  
	
	////////////////////////////
	// block store operations //
	////////////////////////////

	/**
	 * @param volumeId
	 * @param instanceId
	 * @param device
	 * @return
	 * @throws EC2Exception
	 */
	public abstract AttachmentInfo attachVolume(String volumeId, String instanceId, String device) throws EC2Exception;

	/**
	 * @param volumeId
	 * @param instanceId
	 * @param device
	 * @return
	 * @throws EC2Exception
	 */
	public abstract AttachmentInfo detachVolume(String volumeId, String instanceId, String device) throws EC2Exception;

	/**
	 * @param volumeId
	 * @param instanceId
	 * @param device
	 * @param force
	 * @return
	 * @throws EC2Exception
	 */
	public abstract AttachmentInfo detachVolume(String volumeId, String instanceId, String device, boolean force) throws EC2Exception;

	/**
	 * @param volumeId
	 * @return
	 */
	public abstract Snapshot createSnapshot(String volumeId) throws EC2Exception;

	/**
	 * @return
	 */
	public abstract List<Snapshot> describeSnapshots() throws EC2Exception;

	/**
	 * @param snapshotIds
	 * @return
	 */
	public abstract List<Snapshot> describeSnapshots(Set<String> snapshotIds) throws EC2Exception;


	/**
	 * @param snapshotId
	 * @return
	 * @throws EC2Exception
	 */
	public abstract boolean deleteSnapshot(String snapshotId) throws EC2Exception;

	/**
	 * @param size
	 * @param availabilityZoneName
	 * @return
	 * @throws EC2Exception
	 */
	public abstract Volume createVolume(int size, String availabilityZoneName) throws EC2Exception;
	
	/**
	 * @param snapshotId
	 * @param availabilityZoneName
	 * @return
	 * @throws EC2Exception
	 */
	public abstract Volume createVolume(String snapshotId, String availabilityZoneName) throws EC2Exception;
	
	/**
	 * @param volumeId
	 * @return
	 * @throws EC2Exception
	 */
	public abstract boolean deleteVolume(String volumeId) throws EC2Exception;

	/**
	 * @return
	 */
	public abstract List<Volume> describeVolumes() throws EC2Exception;
	
	/**
	 * @param volumeIds
	 * @return
	 */
	public abstract List<Volume> describeVolumes(Set<String> volumeIds) throws EC2Exception;
	
	///////////////////////////
	// elastic ip operations //
	///////////////////////////
	
	/**
	 * @return
	 * @throws EC2Exception
	 */
	public abstract String allocateAddress() throws EC2Exception;

	/**
	 * @param instanceId
	 * @param publicIp
	 * @return
	 * @throws EC2Exception
	 */
	public abstract boolean associateAddress(String instanceId, String publicIp) throws EC2Exception;

	/**
	 * @return
	 * @throws EC2Exception
	 */
	public abstract List<Address> describeAddresses() throws EC2Exception;

	/**
	 * @param publicIps
	 * @return
	 * @throws EC2Exception
	 */
	public abstract List<Address> describeAddresses(Set<String> publicIps) throws EC2Exception;

	/**
	 * @param publicIp
	 * @return
	 * @throws EC2Exception
	 */
	public abstract boolean disassociateAddress(String publicIp) throws EC2Exception;

	/**
	 * @param publicIp
	 * @return
	 * @throws EC2Exception
	 */
	public abstract boolean releaseAddress(String publicIp) throws EC2Exception;

	///////////////////
	// Amazon DevPay //
	///////////////////
	
	/**
	 * @param productCode
	 * @param instanceId
	 * @return The instance owner's account ID. 
	 * 		Only present if the product code is attached to the instance. In other case return null.
	 * @throws EC2Exception
	 */
	public abstract String confirmProductInstance(String productCode, String instanceId) throws EC2Exception;
	
	/////////////
	// General //
	/////////////
	
	/**
	 * @param productCode
	 * @param instanceId
	 * @return
	 * @throws EC2Exception
	 */
	public abstract ConsoleOutput getConsoleOutput(String instanceId) throws EC2Exception;
	
	////////////////
	// Monitoring //
	////////////////
	
	/**
	 * @param instanceId
	 * @return
	 * @throws EC2Exception
	 */
	public abstract InstanceMonitoringInfo monitorInstance(String instanceId) throws EC2Exception;

	/**
	 * @param instanceIds
	 * @return
	 * @throws EC2Exception
	 */
	public abstract List<InstanceMonitoringInfo> monitorInstances(Set<String> instanceIds) throws EC2Exception;

	/**
	 * @param instanceId
	 * @return
	 * @throws EC2Exception
	 */
	public abstract InstanceMonitoringInfo unmonitorInstance(String instanceId) throws EC2Exception;

	/**
	 * @param instanceIds
	 * @return
	 * @throws EC2Exception
	 */
	public abstract List<InstanceMonitoringInfo> unmonitorInstances(Set<String> instanceIds) throws EC2Exception;

	/////////////
	// Windows //
	/////////////
	
	/**
	 * @param instanceId
	 * @param bucketId
	 * @param prefix
	 * @param awsAccessKeyId
	 * @param awsSecretKey
	 * @return
	 * @throws EC2Exception
	 */
	public abstract BundleInstanceInfo bundleInstance(String instanceId, String bucketId, String prefix, 
			String awsAccessKeyId, String awsSecretKey) throws EC2Exception; 

	/**
	 * @param bundleId
	 * @return
	 * @throws EC2Exception
	 */
	public abstract BundleInstanceInfo cancelBundleTask(String bundleId) throws EC2Exception; 

	/**
	 * @return
	 * @throws EC2Exception
	 */
	public abstract List<BundleInstanceInfo> describeBundleTasks() throws EC2Exception; 
	
	/**
	 * @param bundleIds
	 * @return
	 * @throws EC2Exception
	 */
	public abstract List<BundleInstanceInfo> describeBundleTasks(Set<String> bundleIds) throws EC2Exception; 
	
	/**
	 * @return the service
	 */
	public abstract AmazonEC2PortType getService();
	
}
